using System;
using System.Linq;
using DevExpress.Xpo;
using DevExpress.ExpressApp;
using DevExpress.Data.Filtering;
using DevExpress.ExpressApp.Xpo;
using DevExpress.Persistent.Base;
using DevExpress.ExpressApp.Updating;
using DevExpress.Persistent.BaseImpl;
using DevExpress.ExpressApp.Security;
using DevExpress.ExpressApp.Security.Strategy;
using SecurityDemo.Module.BusinessObjects;
using SecurityDemo.Module.BusinessObjects.MemberLevel;
using SecurityDemo.Module.BusinessObjects.ObjectLevel;
//using DevExpress.ExpressApp.Reports;
//using DevExpress.ExpressApp.PivotChart;
//using DevExpress.ExpressApp.Security.Strategy;
//using SecurityDemo.Module.BusinessObjects;

namespace SecurityDemo.Module.DatabaseUpdate
{
    // For more typical usage scenarios, be sure to check out http://documentation.devexpress.com/#Xaf/clsDevExpressExpressAppUpdatingModuleUpdatertopic
    public class Updater : ModuleUpdater
    {
        public Updater(IObjectSpace objectSpace, Version currentDBVersion) :
            base(objectSpace, currentDBVersion)
        {
        }
        public override void UpdateDatabaseAfterUpdateSchema()
        {
            base.UpdateDatabaseAfterUpdateSchema();
            //string name = "MyName";
            //DomainObject1 theObject = ObjectSpace.FindObject<DomainObject1>(CriteriaOperator.Parse("Name=?", name));
            //if(theObject == null) {
            //    theObject = ObjectSpace.CreateObject<DomainObject1>();
            //    theObject.Name = name;
            //}

            SecuritySystemRole defaultRole = CreateDefaultRole();
            SecuritySystemRole administratorRole = CreateAdministratorRole();

            SecuritySystemUser userAdmin = ObjectSpace.FindObject<SecuritySystemUser>(new BinaryOperator("UserName", "Sam"));
            if (userAdmin == null)
            {
                userAdmin = ObjectSpace.CreateObject<SecuritySystemUser>();
                userAdmin.UserName = "Sam";
                userAdmin.IsActive = true;
                userAdmin.SetPassword("");
                userAdmin.Roles.Add(administratorRole);
            }

            SecuritySystemRole securityDemoRole = CreateSecurityDemoRole();

            SecuritySystemUser userJohn = ObjectSpace.FindObject<SecuritySystemUser>(new BinaryOperator("UserName", "John"));
            if (userJohn == null)
            {
                userJohn = ObjectSpace.CreateObject<SecuritySystemUser>();
                userJohn.UserName = "John";
                userJohn.IsActive = true;
                userJohn.Roles.Add(defaultRole);
                userJohn.Roles.Add(securityDemoRole);
                userJohn.Save();
            }

            ObjectSpace.CommitChanges();
        }


        public override void UpdateDatabaseBeforeUpdateSchema()
        {
            base.UpdateDatabaseBeforeUpdateSchema();
            //if(CurrentDBVersion < new Version("1.1.0.0") && CurrentDBVersion > new Version("0.0.0.0")) {
            //    RenameColumn("DomainObject1Table", "OldColumnName", "NewColumnName");
            //}

            
        }


        private SecuritySystemRole CreateAdministratorRole()
        {
            SecuritySystemRole administratorRole = ObjectSpace.FindObject<SecuritySystemRole>(new BinaryOperator("Name", "Administrator"));
            if (administratorRole == null)
            {
                administratorRole = ObjectSpace.CreateObject<SecuritySystemRole>();
                administratorRole.Name = "Administrator";
                administratorRole.IsAdministrative = true;
            }
            return administratorRole;
        }
        private SecuritySystemRole CreateDefaultRole()
        {
            SecuritySystemRole defaultRole = ObjectSpace.FindObject<SecuritySystemRole>(new BinaryOperator("Name", "Default"));
            if (defaultRole == null)
            {
                defaultRole = ObjectSpace.CreateObject<SecuritySystemRole>();
                defaultRole.Name = "Default";

                defaultRole.AddObjectAccessPermission<SecuritySystemUser>("[Oid] = CurrentUserId()", SecurityOperations.ReadOnlyAccess);
                defaultRole.AddMemberAccessPermission<SecuritySystemUser>("ChangePasswordOnFirstLogon; StoredPassword", SecurityOperations.ReadWriteAccess);
                defaultRole.AddObjectAccessPermission<SecuritySystemRole>("[Name] = 'Default'", SecurityOperations.ReadOnlyAccess);
            }
            return defaultRole;
        }

        private SecuritySystemRole CreateSecurityDemoRole()
        {
            SecuritySystemRole securityDemoRole = ObjectSpace.FindObject<SecuritySystemRole>(new BinaryOperator("Name", "Demo"));
            if (securityDemoRole == null)
            {
                securityDemoRole = ObjectSpace.CreateObject<SecuritySystemRole>();
                securityDemoRole.Name = "Demo";

                // Type Operation Permissions
                securityDemoRole.EnsureTypePermissions<FullAccessObject>(SecurityOperations.FullAccess);
                securityDemoRole.EnsureTypePermissions<ProtectedContentObject>(SecurityOperations.Navigate);
                securityDemoRole.EnsureTypePermissions<ReadOnlyObject>(SecurityOperations.ReadOnlyAccess);
                securityDemoRole.EnsureTypePermissions<IrremovableObject>(SecurityOperations.Navigate + ";" + SecurityOperations.Create + ";" + SecurityOperations.ReadWriteAccess);
                securityDemoRole.EnsureTypePermissions<UncreatableObject>(SecurityOperations.FullObjectAccess);

                // Member Operation Permissions
                securityDemoRole.EnsureTypePermissions<MemberLevelSecurityObject>(SecurityOperations.Navigate + ";" + SecurityOperations.Create + ";" + SecurityOperations.Delete);
                securityDemoRole.AddMemberAccessPermission<MemberLevelSecurityObject>("ReadWriteProperty;Name;oid;Oid;OptimisticLockField", SecurityOperations.ReadWriteAccess);
                securityDemoRole.AddMemberAccessPermission<MemberLevelSecurityObject>("ReadOnlyProperty;ReadOnlyCollection", SecurityOperations.Read);

                securityDemoRole.EnsureTypePermissions<MemberLevelReferencedObject1>(SecurityOperations.CRUDAccess);
                securityDemoRole.EnsureTypePermissions<MemberLevelReferencedObject2>(SecurityOperations.CRUDAccess);

                // Object Operation Permissions
                securityDemoRole.EnsureTypePermissions<ObjectLevelSecurityObject>(SecurityOperations.Navigate);
                securityDemoRole.AddObjectAccessPermission<ObjectLevelSecurityObject>("[Name] Like '%Fully Accessible%'", SecurityOperations.FullObjectAccess);
                securityDemoRole.AddObjectAccessPermission<ObjectLevelSecurityObject>("[Name] Like '%Read-Only%'", SecurityOperations.Read);
                securityDemoRole.AddObjectAccessPermission<ObjectLevelSecurityObject>("[Name] Like '%Protected Deletion%'", SecurityOperations.ReadWriteAccess);

                // Member By Criteria Operation Permissions
                securityDemoRole.EnsureTypePermissions<MemberByCriteriaSecurityObject>(SecurityOperations.Navigate);
                securityDemoRole.AddMemberAccessPermission<MemberByCriteriaSecurityObject>("Name", SecurityOperations.ReadWriteAccess, "[Name] <> 'No Read Access Object'");
                securityDemoRole.AddMemberAccessPermission<MemberByCriteriaSecurityObject>("Property1;ReferenceProperty;Oid;oid", SecurityOperations.ReadWriteAccess, "[Name] = 'Fully Accessible Property Object'");
                securityDemoRole.AddMemberAccessPermission<MemberByCriteriaSecurityObject>("Property1;ReferenceProperty;Oid;oid", SecurityOperations.Read, "[Name] = 'Read-Only Property Object'");
            }
            return securityDemoRole;
        }
    }
}
